package com.zznj.xzjc.utils.fileutils;

import android.os.Handler;
import android.util.Log;

import com.zznj.xzjc.utils.FileUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class OkManager {
    private File rootFile;//文件的路径
    private final ThreadPoolExecutor executor;// 线程池
    private Map<String, Boolean> stateMap = new HashMap<>();
    private static OkManager instance;
    private Map<String, Thread> threadMap = new HashMap<>();

    public static OkManager getInstance() {
        synchronized (OkManager.class) {
            if (instance == null) {
                instance = new OkManager();
            }
        }
        return instance;
    }


    public OkManager() {
        rootFile = FileUtils.getRootFile();
        executor = new ThreadPoolExecutor(5, 5, 50, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3000));
    }

    public void downLoadFile(String downUrl,String fileName, DownLoad.IProgress progress, Handler handler) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                downLoad(downUrl,fileName, progress, handler);
            }
        };
        threadMap.put(downUrl, thread);
        stateMap.put(downUrl, true);
        executor.execute(thread);
    }

    public void downLoadFile(String downUrl,String fileName, Handler handler) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                downLoad(downUrl,fileName, handler);
            }
        };
        executor.execute(thread);
    }

    /**
     * 这就是下载方法
     */
    private void downLoad(String downUrl,String fileName, DownLoad.IProgress progress, Handler handler) {
        try {
            File file = new File(rootFile,fileName);
            long downLoadSize = 0;
            long totalSize = getContentLength(downUrl);
            if (!file.exists()) {
                file.createNewFile();
            } else {
                downLoadSize = file.length();
                if (downLoadSize == totalSize) {
                    return;
                }
            }
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            raf.seek(downLoadSize);


            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(downUrl).addHeader("Range", "bytes=" + downLoadSize + "-" + totalSize).build();
            Response response = client.newCall(request).execute();
            InputStream ins = response.body().byteStream();
            //上面的就是简单的OKHttp连接网络，通过输入流进行写入到本地
            int len = 0;
            byte[] by = new byte[1024];
            long endTime = System.currentTimeMillis();
            while ((len = ins.read(by)) != -1 && stateMap.get(downUrl)) {//如果下载没有出错并且已经开始下载，循环进行以下方法
                raf.write(by, 0, len);
                downLoadSize += len;
                if (System.currentTimeMillis() - endTime > 1000) {
                    final double dd = downLoadSize / (totalSize * 1.0);
                    DecimalFormat format = new DecimalFormat("#0.00");
                    String value = format.format((dd * 100)) + "%";//计算百分比
                    Log.i("tag", "==================" + value);
                    if(handler != null){
                        handler.post(new Runnable() {//通过Handler发送消息到UI线程，更新
                            @Override
                            public void run() {
                                if(progress != null){
                                    progress.onProgress((int) (dd * 100));
                                }
                            }
                        });
                    }
                    if (downLoadSize == totalSize) {
                        stateMap.remove(downUrl);
                        executor.remove(threadMap.get(downUrl));
                        threadMap.remove(downUrl);
                        file.renameTo(FileUtils.getFinishFile(downUrl));
                    }
                }
            }
            response.close();//最后要把response关闭
        } catch (Exception e) {
            e.getMessage();
            stateMap.remove(downUrl);
            executor.remove(threadMap.get(downUrl));
            threadMap.remove(downUrl);
        }

    }

    /**
     * 这就是下载方法
     */
    private void downLoad(String downUrl,String fileName, Handler handler) {
        try {
            File file = new File(rootFile,fileName);
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);

            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(downUrl).build();
            Response response = client.newCall(request).execute();
            InputStream ins = response.body().byteStream();
            //上面的就是简单的OKHttp连接网络，通过输入流进行写入到本地
            int len = 0;
            byte[] by = new byte[1024];
            long endTime = System.currentTimeMillis();
            while ((len = ins.read(by)) != -1) {
                fos.write(by, 0, len);
            }
            fos.flush();
            handler.sendEmptyMessage(100);
            response.close();//最后要把response关闭
        } catch (Exception e) {
            e.getMessage();
            handler.sendEmptyMessage(-1);
        }

    }


    //通过OkhttpClient获取文件的大小
    public long getContentLength(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        long length = response.body().contentLength();
        response.close();
        return length;
    }
}